﻿using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading;

namespace Dot5Demo
{
    public class AnimateImage
    {
        private FrameDimension frameDimension;
        private Image image;
        private object _loclobj = new object();
        private bool mCanAnimate;
        private int mFrameCount = 1, mCurrentFrame = 0;

        /// 实例化一个AnimateImage。
        /// </summary>
        /// <param name="img">动画图片。</param>
        public AnimateImage(Image img)
        {
            LoopPlay = true;
            if (img == null)
                return;
            SetImage(img);
        }

        public AnimateImage() : this(null)
        {

        }

        public void SetImage(Image img)
        {
            image = img;
            EnterLock();
            mCanAnimate = ImageAnimator.CanAnimate(image);
            if (mCanAnimate)
            {
                Guid[] guid = image.FrameDimensionsList;
                frameDimension = new FrameDimension(guid[0]);
                mFrameCount = image.GetFrameCount(frameDimension);
            }
            ExitLock();
        }
        //// <summary>
        /// 动画当前帧发生改变时触发。
        /// </summary>
        public event EventHandler<EventArgs> OnFrameChanged;

        public bool CanAnimate
        {
            get { return mCanAnimate; }
        }

        public int CurrentFrame
        {
            get { return mCurrentFrame; }
        }

        public int FrameCount
        {
            get { return mFrameCount; }
        }

        public Image Image
        {
            get { return image; }
        }

        public bool LoopPlay { get; set; }
        public void Play()
        {
            if (mCanAnimate)
            {
                EnterLock();
                ImageAnimator.Animate(image, new EventHandler(FrameChanged));

                ExitLock();
            }
        }

        public void Reset()
        {
            if (mCanAnimate)
            {
                EnterLock();
                ImageAnimator.StopAnimate(image, new EventHandler(FrameChanged));
                image.SelectActiveFrame(frameDimension, 0);
                mCurrentFrame = 0;
                ExitLock();
            }
        }

        public void Stop()
        {
            if (mCanAnimate)
            {
                EnterLock();
                ImageAnimator.StopAnimate(image, new EventHandler(FrameChanged));
                ExitLock();
            }
        }

        private void FrameChanged(object sender, EventArgs e)
        {
            var newf = mCurrentFrame + 1;
            if (newf >= mFrameCount)
            {
                if (LoopPlay)
                    mCurrentFrame = 0;
            }
            else
                mCurrentFrame = newf;
            mCurrentFrame = mCurrentFrame + 1 >= mFrameCount ? 0 : mCurrentFrame + 1;
            EnterLock();
            image.SelectActiveFrame(frameDimension, mCurrentFrame);
            if (OnFrameChanged != null)
            {
                OnFrameChanged(image, e);
            }
            ExitLock();
        }

        public void EnterLock()
        {
            Monitor.Enter(_loclobj);
        }

        public void ExitLock()
        {
            Monitor.Exit(_loclobj);
        }
    }
}